package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.ForegroudOnly
import io.shuttle.mbe.api.annotation.LowerEqMV2
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.Value3Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.api.types.Window
import io.shuttle.mbe.core.Promise

////////////////////
// Extension
////////////////////
/**
 * The `Browser.extension` API has utilities that can be used by any extension page. It includes support for exchanging messages between an extension and its content scripts or between extensions, as described in detail in Message Passing.
 */
interface Extension {
    // True for content scripts running inside incognito tabs,
    // and for extension pages running inside an incognito process.
    // The latter only applies to extensions with 'split' incognito_behavior.
    var inIncognitoContext: Boolean
    // Description of the error that has taken place.
    var message: String
    // Set for the lifetime of a callback if an ansychronous extension api has resulted in an error.
    // If no error has occured lastError will be undefined.
    @Deprecated(
        "Deprecated since Chrome 58",
        replaceWith = ReplaceWith("Please use runtime.lastError.")
    )
    @LowerEqMV2
    var lastError: LastError
    // Returns the JavaScript 'window' object for the background page running inside the current extension.
    // Returns null if the extension has no background page.
    @ForegroudOnly
    abstract fun getBackgroundPage(): Window?

    // Returns an array of the JavaScript 'window' objects for each of the tabs running inside the current extension.
    // If windowId is specified, returns only the 'window' objects of tabs attached to the specified window.
    @ForegroudOnly
    @Deprecated(
        "Deprecated",
        replaceWith = ReplaceWith("Please use extension.getViews {type: \"tab\"}.")
    )
    @LowerEqMV2
    abstract fun getExtensionTabs(windowId: Number?): List<Window>

    // Converts a relative path within an extension install directory to a fully-qualified URL.
    // @return The fully-qualified URL to the resource.
    @LowerEqMV2
    @Deprecated(
        "Deprecated since Chrome 58",
        replaceWith = ReplaceWith("Please use runtime.getURL.")
    )
    abstract fun getURL(
        // A path to a resource within an extension expressed relative to its install directory.
        path: String
    ): String

    // Returns an array of the JavaScript 'window' objects for each of the pages running inside the current extension.
    @ForegroudOnly
    abstract fun getViews(
        fetchProperties: FetchProperties? = null
    ): List<Window>

    // Retrieves the state of the extension's access to the 'file://' scheme.
    // This corresponds to the user-controlled per-extension 'Allow access to File URLs'
    // setting accessible via the chrome://extensions page.
    // @return {callback.isAllowedAccess} True if the extension can access the 'file://' scheme, false otherwise.
    @PromiseStyleMinVersion(99)
    abstract fun isAllowedFileSchemeAccess(callback: Value1Function<Boolean>? = null): Promise<Boolean>

    // Retrieves the state of the extension's access to Incognito-mode.
    // This corresponds to the user-controlled per-extension 'Allowed in Incognito' setting accessible via the chrome://extensions page.
    // @return {callback.isAllowedAccess} True if the extension can access the 'file://' scheme, false otherwise.
    @PromiseStyleMinVersion(99)
    abstract fun isAllowedIncognitoAccess(callback: Value1Function<Boolean>? = null): Promise<Boolean>

    // Sends a single request to other listeners within the extension.
    // Similar to runtime.connect, but only sends a single request with an optional response.
    // The extension.onRequest event is fired in each page of the extension.
    // @return {callback.response} The JSON response object sent by the handler of the request.
    // If an error occurs while connecting to the extension,
    // the callback will be called with no arguments and runtime.lastError will be set to the error message.
    @Deprecated("Deprecate", replaceWith = ReplaceWith("Please use runtime.sendMessage"))
    @LowerEqMV2
    @PromiseStyleMinVersion(99)
    abstract fun sendRequest(
        // The extension ID of the extension you want to connect to. If omitted, default is your own extension.
        extensionId: String?,
        request: Any,
        callback: Value1Function<Any>? = null
    ): Promise<Any>

    // Sets the value of the ap CGI parameter used in the extension's update URL.
    // This value is ignored for extensions that are hosted in the Chrome Extension Gallery.
    abstract fun setUpdateUrlData(data: String)

    // Fired when a request is sent from either an extension process or a content script.
    @LowerEqMV2
    @Deprecated("Deprecate", replaceWith = ReplaceWith("Please use runtime.onMessage"))
    abstract val onRequest: Events.Event<Value3Function<Any, Any/*runtime.MessageSender*/, VoidFunction>>

    // Fired when a request is sent from another extension.
    @LowerEqMV2
    @Deprecated("Deprecate", replaceWith = ReplaceWith("Please use runtime.onMessageExternal."))
    abstract val onRequestExternal: Events.Event<Value3Function<Any, Any/*runtime.MessageSender*/, VoidFunction>>

    // The type of extension view.
    @ChromeMinVersion(44)
    enum class ViewType {
        tab,
        popup,
    }

    data class FetchProperties(
        // Returns an array of the JavaScript 'window' objects for each of the pages running inside the current extension.
        /**
         * Optional.
         * Chrome 54+
         * Find a view according to a tab id. If this field is omitted, returns all views.
         */
        @ChromeMinVersion(54)
        var tabId: Number?,
        // The type of view to get. If omitted, returns all views (including background pages and tabs).
        //  /** Optional. The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'notification', 'popup'.  */
        var type: ViewType?,
        // The window to restrict the search to. If omitted, returns all views.
        var windowId: Number?,
    )

    data class LastError(
        /** Description of the error that has taken place. */
        var message: String
    )
}